package com.bole.springboot_webflux.controller;

import com.bole.springboot_webflux.dao.AttachmentRepository;
import com.bole.springboot_webflux.model.AttachmentModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ZeroCopyHttpOutputMessage;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.File;
import java.net.URLEncoder;
import java.nio.file.Paths;
import java.util.UUID;

@RestController
@RequestMapping("/annotated/")
public class WebFluxController {

    private static final Logger log = LoggerFactory.getLogger(WebFluxController.class);
    @Autowired
    private AttachmentRepository attachmentRepository;
    @Autowired
    private org.springframework.data.r2dbc.core.R2dbcEntityTemplate r2dbcEntityTemplate;

    @GetMapping("/greeting")
    public Mono<String> greeting(){

        return Mono.just("hello webflux by annotated");
    }

    @GetMapping("/flux/test")
    public Flux<Integer> fluxTest(){
        return Flux.just(1,2,3,4,5);
    }

    @RequestMapping("/getAttachment/{id}")
    public Mono<AttachmentModel> getAttachment(@PathVariable("id") String id) throws InterruptedException {
        Thread.sleep(2000);
        Mono<AttachmentModel> mono = attachmentRepository.findById(id);
        System.out.println("1111" + System.currentTimeMillis());
        return mono;
    }

    @RequestMapping("/getAttachmentBody")
    public Mono<AttachmentModel> getAttachmentBody(@RequestBody AttachmentModel model) throws InterruptedException {
        Mono<AttachmentModel> mono = attachmentRepository.findById(model.getId());
        System.out.println("1111" + System.currentTimeMillis());
        return mono;
    }

    @RequestMapping("/addUser")
    public Mono<AttachmentModel> addAttachment(AttachmentModel model) {
        Mono<AttachmentModel> mono = attachmentRepository.save(model);
        return mono;
    }


    // 方法二：使用 ServerHttpResponse 进行零拷贝下载（性能最优）
    @GetMapping("/download-zero-copy/{filename}")
    public Mono<Void> downloadFileZeroCopy(@PathVariable String filename, ServerHttpResponse response) {
        return Mono.fromCallable(() -> Paths.get("D:\\TEMP\\", filename).toAbsolutePath().normalize())
                .flatMap(filePath -> {
                    File file = filePath.toFile();
                    if (!file.exists()) {
                        return Mono.error(new RuntimeException("File not found: " + filename));
                    }
                    ZeroCopyHttpOutputMessage zeroCopyResponse = (ZeroCopyHttpOutputMessage) response;

                    response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION,
                            "attachment; filename=\"" + URLEncoder.encode(file.getName()) + "\"");
                    response.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);

                    // 零拷贝：直接将文件从磁盘传输到网络，不经过应用内存
                    return zeroCopyResponse.writeWith(file, 0, file.length());
                });
    }

    @RequestMapping("/addAndDelete")
    public Mono<Void> addAndDelete() {
        AttachmentModel model = new AttachmentModel();
        model.setId(UUID.randomUUID().toString().replaceAll("-",""));
        model.setApplyNo("666");
        model.setDataId("DataId");
        // Mono<AttachmentModel> addMono = attachmentRepository.save(model);
        Mono<AttachmentModel> addMono = r2dbcEntityTemplate.insert(model);
        addMono.subscribe(add ->{
            System.out.println("add: " + add);
        });
        Mono<Void> delMono = attachmentRepository.deleteById("04b552fc72fa4cccb4ed9d46f516fd74");
        delMono.subscribe(del ->{
            System.out.println("del: " + del);
        });
        System.out.println("666666666666666666");
        return Mono.empty();
    }

}

